@file:Suppress("RedundantSuspendModifier")

class Cache {
    private val cache = mutableMapOf<String, String>()
    fun load(key: String): String? = cache[key]
    fun store(key: String, value: String) { cache[key] = value }
    fun dumpToString(): String = cache.entries.sortedBy { it.key }.joinToString(",") { it.key + "=" + it.value }
}

class OperatorsToNonOperators(private val cache: Cache) {
    fun get(key: String): String? = cache.load(key)
    fun set(key: String, value: String) = cache.store(key, value)
    fun invoke(): String = cache.dumpToString()

    companion object {
        fun Cache.get(key: String): String? = load(key)
        fun Cache.set(key: String, value: String) = store(key, value)
        fun Cache.invoke(): String = dumpToString()
    }
}

class NonOperatorsToOperators(private val cache: Cache) {
    operator fun get(key: String): String? = cache.load(key)
    operator fun set(key: String, value: String) = cache.store(key, value)
    operator fun invoke(): String = cache.dumpToString()

    companion object {
        operator fun Cache.get(key: String): String? = load(key)
        operator fun Cache.set(key: String, value: String) = store(key, value)
        operator fun Cache.invoke(): String = dumpToString()
    }
}

data class Wrapper(private val value: Int) {
    private operator fun plus(other: Wrapper): Wrapper = (value + other.value).wrap()
    fun unwrap(): Int = value

    infix fun memberNonInfixToInfix(other: Wrapper): Wrapper = this + other
    fun memberInfixToNonInfix(other: Wrapper): Wrapper = this + other

    companion object {
        infix fun Wrapper.extensionNonInfixToInfix(other: Wrapper): Wrapper = this + other
        fun Wrapper.extensionInfixToNonInfix(other: Wrapper): Wrapper = this + other
    }
}

fun Int.wrap(): Wrapper = Wrapper(this)

object Functions {
    tailrec fun nonTailrecToTailrec(n: Int, r: Int): Int = if (n <= 1) r else nonTailrecToTailrec(n - 1, n * r)
    fun tailrecToNonTailrec(n: Int, r: Int): Int = if (n <= 1) r else tailrecToNonTailrec(n - 1, n * r)

    @Suppress("RedundantSuspendModifier") suspend fun <R> wrapCoroutine(coroutine: suspend () -> R): R = coroutine.invoke()
    fun suspendToNonSuspendFunction(x: Int): Int = -x
    suspend fun nonSuspendToSuspendFunction(x: Int): Int = wrapCoroutine { -x }

    fun removedFirstDefaultValue(a: Int /*= 42*/, b: Int): Int = a + b
    fun removedVarargFirstDefaultValue(vararg a: Int /*= intArrayOf(1, 2, 3)*/, b: Int): Int = a.sum() + b
    fun removedLastDefaultValue(a: Int, b: Int /*= 42*/): Int = a + b
    fun removedVarargLastDefaultValue(a: Int, vararg b: Int /*= intArrayOf(1, 2, 3)*/): Int = a + b.sum()
}

class RemovedFirstDefaultValueInConstructor(a: Int /*= 42*/, b: Int) {
    val value = a + b
}
class RemovedLastDefaultValueInConstructor(a: Int, b: Int /*= 42*/) {
    val value = a + b
}

interface Interface {
    fun suspendToNonSuspendFunction(x: Int): String
    suspend fun nonSuspendToSuspendFunction(x: Int): String
}

abstract class AbstractClass {
    abstract fun suspendToNonSuspendFunction(x: Int): String
    abstract suspend fun nonSuspendToSuspendFunction(x: Int): String
}

open class OpenClass {
    open fun suspendToNonSuspendFunction(x: Int): String = "OpenClassV2.suspendToNonSuspendFunction($x)"
    open suspend fun nonSuspendToSuspendFunction(x: Int): String = Functions.wrapCoroutine { "OpenClassV2.nonSuspendToSuspendFunction($x)" }

    open fun suspendToNonSuspendFunctionWithDelegation(x: Int): String = "OpenClassV2.suspendToNonSuspendFunctionWithDelegation($x)"
    open suspend fun nonSuspendToSuspendFunctionWithDelegation(x: Int): String = Functions.wrapCoroutine { "OpenClassV2.nonSuspendToSuspendFunctionWithDelegation($x)" }
}


interface KT59153 {
    // fun test(f: () -> String) = "foo".run { f() }
    fun test(f: Any.() -> String) = "foo".run { f() }
}
